package org.pine.common.beans;

import cn.hutool.core.lang.Snowflake;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.concurrent.ThreadLocalRandom;

/**
 * ID生成器
 *
 * @author pine
 * @version 1.0
 * @since 2025-04-10 18:26
 */
public class IdGenerator {

    private static final Snowflake SNOWFLAKE;

    /**
     * 最大WorkerId（31）
     */
    private static final long WORKER_ID_MAX = 31L;

    static {
        String dataCenterIdStr = System.getProperty("dataCenterId", "1");
        long dataCenterId = Long.parseLong(dataCenterIdStr);
        SNOWFLAKE = new Snowflake(generateWorkerId(), dataCenterId);
    }

    /**
     * 根据IP地址和线程信息生成workerId
     *
     * @return workerId（10位）
     */
    private static long generateWorkerId() {
        try {
            // 1. 获取IP地址哈希（5位）， 保留5位
            int ipHash = getIpHash() % (1 << 5);

            // 2. 获取随机ID哈希（5位）
            int randomHash = ThreadLocalRandom.current().nextInt(1 << 5);

            // 3. 组合生成10位workerId，0x1F = 5位掩码
            return ((ipHash << 5) | (randomHash & 0x1F)) % WORKER_ID_MAX;
        } catch (UnknownHostException e) {
            throw new RuntimeException("Failed to generate workerId", e);
        }
    }

    /**
     * 根据IP地址生成哈希值
     *
     * @return IP哈希值
     * @throws UnknownHostException 当无法获取本地IP时抛出
     */
    private static int getIpHash() throws UnknownHostException {
        InetAddress ip = InetAddress.getLocalHost();
        byte[] address = ip.getAddress();
        return ((address[address.length - 2] & 0xFF) << 8)
                | (address[address.length - 1] & 0xFF);
    }

    public static long nextId() {
        return SNOWFLAKE.nextId();
    }

    public static String nextIdStr() {
        return String.valueOf(nextId());
    }
}
